package initialize

import (
	"fmt"
	"github.com/flipped-aurora/gin-vue-admin/server/docs"
	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/middleware"
	"github.com/flipped-aurora/gin-vue-admin/server/router"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	ginSwagger "github.com/swaggo/gin-swagger"
	"github.com/swaggo/gin-swagger/swaggerFiles"
	"net/http"
	"os"
	"strconv"
)

// 初始化总路由

func Routers() *gin.Engine {
	Router := gin.Default()
	// 解决跨域问题
	config := cors.DefaultConfig()
	config.AllowAllOrigins = true
	Router.Use(cors.New(config))

	InstallPlugin(Router) // 安装插件
	systemRouter := router.RouterGroupApp.System
	exampleRouter := router.RouterGroupApp.Example
	// 如果想要不使用nginx代理前端网页，可以修改 web/.env.production 下的
	// VUE_APP_BASE_API = /
	// VUE_APP_BASE_PATH = http://localhost
	// 然后执行打包命令 npm run build。在打开下面4行注释
	// Router.LoadHTMLGlob("./dist/*.html") // npm打包成dist的路径
	// Router.Static("/favicon.ico", "./dist/favicon.ico")
	// Router.Static("/static", "./dist/assets")   // dist里面的静态资源
	// Router.StaticFile("/", "./dist/index.html") // 前端网页入口页面

	Router.StaticFS(global.GVA_CONFIG.Local.StorePath, http.Dir(global.GVA_CONFIG.Local.StorePath)) // 为用户头像和文件提供静态地址
	Router.StaticFS("backup/file", http.Dir("backup/file"))
	Router.GET("/download", DownloadFile)
	// 为用户上传的excel文件提供静态地址
	// Router.Use(middleware.LoadTls())  // 如果需要使用https 请打开此中间件 然后前往 core/server.go 将启动模式 更变为 Router.RunTLS("端口","你的cre/pem文件","你的key文件")
	// 跨域，如需跨域可以打开下面的注释
	Router.Use(middleware.Cors()) // 直接放行全部跨域请求
	// Router.Use(middleware.CorsByRules()) // 按照配置的规则放行跨域请求
	//global.GVA_LOG.Info("use middleware cors")
	docs.SwaggerInfo.BasePath = global.GVA_CONFIG.System.RouterPrefix
	Router.GET(global.GVA_CONFIG.System.RouterPrefix+"/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
	global.GVA_LOG.Info("register swagger handler")
	// 方便统一添加路由组前缀 多服务器上线使用

	PublicGroup := Router.Group(global.GVA_CONFIG.System.RouterPrefix)
	{
		// 健康监测
		PublicGroup.GET("/health", func(c *gin.Context) {
			c.JSON(http.StatusOK, "ok")
		})
	}
	{
		systemRouter.InitBaseRouter(PublicGroup) // 注册基础功能路由 不做鉴权
		systemRouter.InitInitRouter(PublicGroup) // 自动初始化相关
	}
	PrivateGroup := Router.Group(global.GVA_CONFIG.System.RouterPrefix)
	PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
	{
		systemRouter.InitApiRouter(PrivateGroup)                 // 注册功能api路由
		systemRouter.InitJwtRouter(PrivateGroup)                 // jwt相关路由
		systemRouter.InitUserRouter(PrivateGroup)                // 注册用户路由
		systemRouter.InitMenuRouter(PrivateGroup)                // 注册menu路由
		systemRouter.InitSystemRouter(PrivateGroup)              // system相关路由
		systemRouter.InitCasbinRouter(PrivateGroup)              // 权限相关路由
		systemRouter.InitAutoCodeRouter(PrivateGroup)            // 创建自动化代码
		systemRouter.InitAuthorityRouter(PrivateGroup)           // 注册角色路由
		systemRouter.InitSysDictionaryRouter(PrivateGroup)       // 字典管理
		systemRouter.InitAutoCodeHistoryRouter(PrivateGroup)     // 自动化代码历史
		systemRouter.InitSysOperationRecordRouter(PrivateGroup)  // 操作记录
		systemRouter.InitSysDictionaryDetailRouter(PrivateGroup) // 字典详情管理
		systemRouter.InitAuthorityBtnRouterRouter(PrivateGroup)  // 字典详情管理
		systemRouter.InitChatGptRouter(PrivateGroup)             // chatGpt接口

		exampleRouter.InitCustomerRouter(PrivateGroup)              // 客户路由
		exampleRouter.InitFileUploadAndDownloadRouter(PrivateGroup) // 文件上传下载功能路由

	}
	{
		sampleDataManageRouter := router.RouterGroupApp.SampleDataManage
		sampleDataManageRouter.InitSampleDataRouter(PrivateGroup)
	}
	{
		myUserManageRouter := router.RouterGroupApp.MyUserManage
		myUserManageRouter.InitMyUserManageRouter(PrivateGroup)
	}

	global.GVA_LOG.Info("router register success")
	return Router
}

//func DownloadFile(c *gin.Context) {
//	fmt.Println(c.Query("fileSrc"))
//	filePath := "D:/GOProj/sample_data/server/" + c.Query("fileSrc")
//	//filePath := "/home/sampledata20241008/server/" + c.Query("fileSrc")
//	fileName := c.Query("name")
//	file, err := os.Open(filePath)
//	if err != nil {
//		c.AbortWithError(404, err)
//		return
//	}
//	defer file.Close()
//	stat, err := file.Stat()
//	if err != nil {
//		c.AbortWithError(404, err)
//		return
//	}
//	c.Writer.Header().Set("Content-Disposition", "attachment; filename="+fileName)
//	c.Writer.Header().Set("Content-Type", "application/octet-stream")
//	//流式传输
//	c.Writer.Header().Set("Transfer-Encoding", "chunked")
//	c.Writer.Header().Set("Accept-Ranges", "bytes")
//	c.Writer.Header().Set("Content-Length", strconv.FormatInt(stat.Size(), 10))
//	c.Writer.Flush()
//	var offset int64 = 0
//	var bufsize int64 = 1024 * 1024 // 1MB
//	buf := make([]byte, bufsize)
//	rangeHeader := c.Request.Header.Get("Range")
//	if rangeHeader != "" {
//		parts := strings.Split(rangeHeader, "=")
//		if len(parts) == 2 && parts[0] == "bytes" {
//			rangeStr := parts[1]
//			ranges := strings.Split(rangeStr, "-")
//			if len(ranges) == 2 {
//				offset, _ = strconv.ParseInt(ranges[0], 10, 64)
//				if offset >= stat.Size() {
//					c.AbortWithError(416, fmt.Errorf("Requested Range Not Satisfiable"))
//					return
//				}
//				if ranges[1] != "" {
//					endOffset, _ := strconv.ParseInt(ranges[1], 10, 64)
//					if endOffset >= stat.Size() {
//						endOffset = stat.Size() - 1
//					}
//					c.Writer.Header().Set("Content-Range", "bytes "+ranges[0]+"-"+strconv.FormatInt(endOffset, 10)+"/"+strconv.FormatInt(stat.Size(), 10))
//					c.Writer.Header().Set("Content-Length", strconv.FormatInt(endOffset-offset+1, 10))
//					file.Seek(offset, 0)
//				} else {
//					c.Writer.Header().Set("Content-Range", "bytes "+ranges[0]+"-"+strconv.FormatInt(stat.Size()-1, 10)+"/"+strconv.FormatInt(stat.Size(), 10))
//					c.Writer.Header().Set("Content-Length", strconv.FormatInt(stat.Size()-offset, 10))
//					file.Seek(offset, 0)
//				}
//				c.Writer.WriteHeader(206)
//			}
//		}
//	}
//	for {
//		n, err := file.ReadAt(buf, offset)
//		if err != nil && err != io.EOF {
//			log.Println("read file error", err)
//			break
//		}
//		if n == 0 {
//			break
//		}
//		_, err = c.Writer.Write(buf[:n])
//		if err != nil {
//			log.Println("write file error", err)
//			break
//		}
//		offset += int64(n)
//	}
//	c.Writer.Flush()
//}

func DownloadFile(c *gin.Context) {
	filePath := "E:/2024demo/sample_data/server/" + c.Query("fileSrc")
	//filePath := "/home/sampledata20241008/server/" + c.Query("fileSrc")
	fileName := c.Query("name")
	file, err := os.Open(filePath)
	if err != nil {
		c.String(http.StatusInternalServerError, "Error opening file")
		return
	}
	defer file.Close()

	fileInfo, err := file.Stat()
	if err != nil {
		c.String(http.StatusInternalServerError, "Error getting file info")
		return
	}

	fileSize := fileInfo.Size()
	rangeHeader := c.GetHeader("Range")

	var start, end int64
	if rangeHeader != "" {
		// Parse the range header
		_, err := fmt.Sscanf(rangeHeader, "bytes=%d-%d", &start, &end)
		if err != nil || start < 0 || end >= fileSize {
			c.String(http.StatusRequestedRangeNotSatisfiable, "Invalid range")
			return
		}
	} else {
		start = 0
		end = fileSize - 1
	}

	c.Header("Content-Disposition", "attachment; filename="+fileName)
	c.Header("Content-Type", "application/octet-stream")
	c.Header("Accept-Ranges", "bytes")
	c.Header("Content-Length", strconv.FormatInt(end-start+1, 10))
	c.Header("Content-Range", fmt.Sprintf("bytes %d-%d/%d", start, end, fileSize))

	_, err = file.Seek(start, 0)
	if err != nil {
		c.String(http.StatusInternalServerError, "Error seeking file")
		return
	}

	buffer := make([]byte, 1024*8)
	for {
		if start > end {
			break
		}
		n, err := file.Read(buffer)
		if err != nil {
			break
		}
		c.Writer.Write(buffer[:n])
		start += int64(n)
	}
}
